package br.edu.ufam.avaliacao
import br.edu.ufam.academico.Curso
class HistoricoController {
    private static final String ANALISE_DIMENSAO = "Análise da Dimensão";
    private static List avaliacoesId = new ArrayList();
    private static List dimensao1Questoes = new ArrayList();
    private static List dimensao2Questoes = new ArrayList();
    private static List dimensao3Questoes = new ArrayList();
    private static FilteredDimensao filteredDimensao;
    private static Long selectedCurso
    private static def currentParams;
    
    def index = {
        List cursos = Curso.executeQuery("select c from Curso c where c.id in (select distinct a.curso from Avaliacao a where a.status = 'Finalizada')");
        [cursoList:cursos]
    }
    
    def bridge = {
        currentParams = params;
    }
    
    def list = {
        if(params.cursoId){
            selectedCurso = Long.parseLong(params.cursoId)
        
            def avaliacaoList = Avaliacao.executeQuery("select a from Avaliacao a where a.curso.id=? and a.status='Finalizada'",[selectedCurso] );
            def curso = Curso.get(selectedCurso) 
            [avaliacaoList:avaliacaoList, cursoName:curso.nomeCursoDiploma, listSize:avaliacaoList.size()]
        }else{
            flash.message = "Não há cursos com mais de uma avaliacao!";
            redirect(action: "index")
        }
    }
    
    def filter1 = {
        def para = params.avaliacaoInstance.id
        if(para && !(para instanceof String)){
            avaliacoesId = para;
        }else{
            flash.message = "É necessário ao menos 2 (duas) avaliacoes para realizar a comparacao";
            redirect(action: "list", params:[cursoId: selectedCurso])
        };
        
    }
    
    def filter2 = {
        final String action = params.filtro;
        if(action.equals("Geral")){
            redirect(action: "bridge", params:[dataListId:avaliacoesId, type:FilterType.GENERAL.toString()]);
        }else{
            []
        }
    }
    
    def filter3 = {
        final String action = params.filtro;
        if(action.equals(" ")){
            redirect(action: "bridge", params:[dataListId:avaliacoesId, type:FilterType.GENERAL.toString()]);
        }else{
            List dimensoes = Dimensao.findAll("from Dimensao where ordem < 4 order by ordem");
            
            dimensao1Questoes = formatQuestoesList(dimensoes.get(0));
            dimensao2Questoes = formatQuestoesList(dimensoes.get(1));
            dimensao3Questoes = formatQuestoesList(dimensoes.get(2));
            if(action.equals("Dimensao 1")){
                filteredDimensao = FilteredDimensao.DIMENSAO_1;
                return [indicadores:dimensao1Questoes]
            }else if(action.equals("Dimensao 2")){
                filteredDimensao = FilteredDimensao.DIMENSAO_2;
                return [indicadores:dimensao2Questoes]
            }else{
                filteredDimensao = FilteredDimensao.DIMENSAO_3;
                return [indicadores:dimensao3Questoes]
            }
        }
    }
    
    def lastFilter = {
        final String action = params.indicador;
        if(action.equals(ANALISE_DIMENSAO)){
            redirect(action: "bridge", params:[dataListId:avaliacoesId, type:FilterType.BY_DIMEN.toString(),dimensao:filteredDimensao.toString()]);
        }else{
            def indicador = extractIndicadorOrdem(action);
            def dimensao = filteredDimensao.toString();
            def dimensaoId = Integer.parseInt(dimensao.substring(dimensao.size()-1,dimensao.size()));
            redirect(action: "bridge", params:[dataListId:avaliacoesId, type:FilterType.BY_INDICADOR.toString(),dimensao:dimensaoId,indicador:indicador]);
        }
    }
    
   
    def chartReport = {
        def avaliacaoListId = currentParams.dataListId;
        def type = currentParams.type;
        def avaliacaoList = new ArrayList();
        for (String id: avaliacaoListId){
            avaliacaoList.add(Avaliacao.get(id));
        }
        final StringBuilder builder = new StringBuilder("Avalicacoes de ");
        if(type.equals(FilterType.GENERAL.toString())){
            [chartTitle:builder.toString(), chartData: formatDataForDefault(avaliacaoList)]    
        }else if (type.equals(FilterType.BY_DIMEN.toString())){
            [chartTitle:builder.toString(), chartData: formatDataForDimensao(avaliacaoList, currentParams.dimensao)]    
        }else if(type.equals(FilterType.BY_INDICADOR.toString())){
            def respostas = new ArrayList();
            def dimensao = Integer.parseInt(currentParams.dimensao);
            def indicador = Integer.parseInt(currentParams.indicador);
            for(final Avaliacao avaliacao : avaliacaoList){
                def resposta = Resposta.executeQuery("select r from Resposta r where r.avaliacao = ? and dimensao = ? and indicador = ?",[avaliacao,dimensao,indicador]);
                respostas.add(resposta.get(0));
            }
            [chartTitle:builder.toString(), chartData: formatDataForIndicador(avaliacaoList, respostas, dimensao, indicador)];
        }
    }
  
    private String[][] formatDataForDefault(final List avaliacaoList){
        final Calendar calendar = new GregorianCalendar();
        final String[][] chartData = new String[avaliacaoList.size()+2][2];
        chartData[0][0]="'Data'"; chartData[0][1]="'Conceito'"; 
        for(int i = 1; i < avaliacaoList.size()+1;i++){
            int j = i-1;
            calendar.setTime(avaliacaoList.get(j).dateEnd);
            chartData[i][0] = "'Avaliaçao "+calendar.get(Calendar.DAY_OF_MONTH)+"/"+formattedMonth(calendar.get(Calendar.MONTH))+"/"+calendar.get(Calendar.YEAR)+"'";
            chartData[i][1] = avaliacaoList.get(j).conceitoFinal;
        }
        chartData[chartData.size()-1][0] = "'Avaliacoes de "+avaliacaoList.get(0).curso.nomeCursoDiploma+"'";
        chartData[chartData.size()-1][1] = "' '";
        println chartData
        return chartData;
        final List formated = new ArrayList();
    }
    
    private String[][] formatDataForDimensao(final List avaliacaoList, final String filteredDimensao){
        final Calendar calendar = new GregorianCalendar();
        final String[][] chartData = new String[avaliacaoList.size()+2][2];
        chartData[0][0]="'Data'"; chartData[0][1]="'Conceito'"; 
        int dim;
        for(int i = 1; i < avaliacaoList.size()+1;i++){
            int j = i-1;
            calendar.setTime(avaliacaoList.get(j).dateEnd);
            chartData[i][0] = "'Avaliaçao "+calendar.get(Calendar.DAY_OF_MONTH)+"/"+formattedMonth(calendar.get(Calendar.MONTH))+"/"+calendar.get(Calendar.YEAR)+"'";
            if(FilteredDimensao.DIMENSAO_1.toString().equals(filteredDimensao)){
                dim = 1;
                chartData[i][1] = avaliacaoList.get(j).conceitoDimensao1;
            }else if(FilteredDimensao.DIMENSAO_2.toString().equals(filteredDimensao)){
                dim = 2;
                chartData[i][1] = avaliacaoList.get(j).conceitoDimensao2;    
            }else{
                dim = 3;
                chartData[i][1] = avaliacaoList.get(j).conceitoDimensao3;    
            }
        }
        def dimensaoT = Dimensao.executeQuery("select d from Dimensao d where d.ordem = ?",[dim]).get(0).titulo;
        chartData[chartData.size()-1][0] = "'Avaliacoes de "+avaliacaoList.get(0).curso.nomeCursoDiploma+ " por Dimensao: " + dimensaoT +"'";
        chartData[chartData.size()-1][1] = "' '";
        return chartData;
    }
    
    private String[][] formatDataForIndicador(final List avaliacaoList, final List respostas, final Integer dim, final Integer indicador){
        final Calendar calendar = new GregorianCalendar();
        final String[][] chartData = new String[avaliacaoList.size()+2][2];
        chartData[0][0]="'Data'"; chartData[0][1]="'Conceito'"; 
        for(int i = 1; i < avaliacaoList.size()+1;i++){
            int j = i-1;
            calendar.setTime(avaliacaoList.get(j).dateEnd);
            chartData[i][0] = "'Avaliaçao "+calendar.get(Calendar.DAY_OF_MONTH)+"/"+formattedMonth(calendar.get(Calendar.MONTH))+"/"+calendar.get(Calendar.YEAR)+"'";
            chartData[i][1] = respostas.get(j).conceito;  
        }
        def dimensaoT = Dimensao.executeQuery("select d from Dimensao d where d.ordem = ?",[dim]).get(0).titulo;
        chartData[chartData.size()-1][0] = "'Avaliacoes de "+avaliacaoList.get(0).curso.nomeCursoDiploma+" pelo Indicador "+indicador+" da Dimensao: "+dimensaoT+"'";
        chartData[chartData.size()-1][1] = "' '";
        return chartData;
    }
    
    private List formatQuestoesList(final Dimensao dimensao){
        final List indicadores = Arrays.asList(dimensao.getIndicador().toArray());
        Collections.sort(indicadores, new IndicadorComparator());
        Collections.sort(indicadores, new IndicadorComparator());
  
        final List formated = new ArrayList();
        formated.add(ANALISE_DIMENSAO);
        formated.addAll(indicadores);
        return formated;
    } 
    
    private String formattedMonth(int month){
        month +=1;
        return month<10?"0"+month:String.valueOf(month);
    }
    
    private Integer extractIndicadorOrdem(final String indicador){
        return Integer.parseInt(indicador.substring(0,indicador.indexOf(" ")));
    }
    
    private static enum FilteredDimensao{
        DIMENSAO_1, DIMENSAO_2, DIMENSAO_3;
    }
    
    private static enum FilterType{
        GENERAL, BY_DIMEN, BY_INDICADOR;
    }
    
    private class IndicadorComparator extends Comparator<Indicador>{
        public int compare(Indicador ind1, Indicador ind2){
            return ind1.ordem.compareTo(ind2.ordem);
        }
    }
    
}
